#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#include <fcntl.h>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>

#define MY_FIFO "my_fifo"    // 命名管道文件名

#define MAX_BUFFER_SIZE PIPE_BUF // 4096 定义在于 limits.h 中

void fifo_read() {
    char buff[MAX_BUFFER_SIZE];
    int fd;
    int n_read;

    printf("***************** read fifo ************************\n");
    // 判断命名管道是否已存在，若尚未创建，则以相应的权限创建
    if (access(MY_FIFO, F_OK) == -1) {
        if ((mkfifo(MY_FIFO, 0666) < 0) && (errno != EEXIST)) {
            printf("Cannot create fifo file\n");
            exit(1);
        }
    }

    // 以只读阻塞方式打开命名管道
    fd = open(MY_FIFO, O_RDONLY);
    if (fd == -1) {
        printf("Open fifo file error\n");
        exit(1);
    }

    memset(buff, 0, sizeof(buff));

    if ((n_read = read(fd, buff, MAX_BUFFER_SIZE)) > 0) {
        printf("Read '%s' from FIFO\n", buff);
    }

    printf("***************** close fifo ************************\n");

    close(fd);

    exit(0);
}

void fifo_write() {
    int fd;
    char buff[] = "this is a fifo test demo";
    int n_write;

    // 等待子进程先运行
    sleep(2);

    // 以只写阻塞方式打开 FIFO 管道
    fd = open(MY_FIFO, O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        printf("Open fifo file error\n");
        exit(1);
    }

    printf("Write '%s' to FIFO\n", buff);

    // 向管道中写入字符串
    n_write = write(fd, buff, MAX_BUFFER_SIZE);

    //等待子进程退出
    if (wait(NULL)) {
        close(fd);
        exit(0);
    }

}

int main() {
    pid_t result;
    // 调用 fork()函数
    result = fork();

    // 通过 result 的值来判断 fork()函数的返回情况，首先进行出错处理
    if (result == -1) {
        printf("Fork error\n");
    } else if (result == 0) {// 返回值为 0 代表子进程
        fifo_read();
    } else {// 返回值大于 0 代表父进程
        fifo_write();
    }

    return result;
}